package middle

import (
	"net/http"
	"pegasus/datatypes"
	"reflect"
	"strings"

	"github.com/dalixu/ginjector"
	"github.com/dalixu/owig"
)

//CheckLogined Logined检测 部分请求是需要游戏角色登录后才能调用
//会在用户登录的链接中 检测是否需要进行角色登录检测
type CheckLogined struct {
	ignores []string
}

//NewCheckLogined 返回CheckLogined
func NewCheckLogined(ignores ...string) *CheckLogined {
	return &CheckLogined{
		ignores: ignores,
	}
}

//Invoke 中间件实现
func (cl *CheckLogined) Invoke(ctx owig.Context) {
	req := ctx.Request()
	contains := false
	for _, v := range cl.ignores {
		if strings.Contains(req.URL.Path, v) {
			contains = true
		}
	}
	if !contains {
		value, err := ctx.Container().Resolve(reflect.TypeOf((*datatypes.SIContent)(nil)).Elem())
		//err != nil 通常意味着在checkSession的忽略列表中 既然不需要检测用户登录 同样不需要检测角色登录
		if err == nil {
			//checksession检测过 已登录的链接但不在角色的忽略列表中
			si := value.Interface().(datatypes.SIContent)
			logined := si.Logined()
			if logined == nil {
				ctx.Response().WriteResult(http.StatusUnauthorized, []byte("角色未登录"))
				return
			}
			//添加Logined依赖注入 推荐使用方法Logined结构 因为SIContent 到真正的接口时可能用户已经切换人物登录了
			builder := ginjector.New()
			builder.Register(func(c ginjector.Container) interface{} { return logined }).As(reflect.TypeOf((*datatypes.SICharacter)(nil)).Elem())
			ctx.UpdateContainer(builder.Build(ctx.Container()))
		}
	}
	ctx.Next()
}
